package utils.molehill
{
	import com.adobe.utils.AGALMiniAssembler;
	
	import flash.display.Stage;
	import flash.display.Stage3D;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DBlendFactor;
	import flash.display3D.Context3DRenderMode;
	import flash.display3D.Context3DVertexBufferFormat;
	import flash.display3D.IndexBuffer3D;
	import flash.display3D.Program3D;
	import flash.display3D.VertexBuffer3D;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.geom.Matrix3D;
	
	import org.molehill.SpriteBIGMoleHill;
	import org.molehill.TexturePool;
	
/**
* 派发显卡初始化完成事件
* */
[Event(name="complete", type="flash.events.Event")]

	public class MoleHillServer extends EventDispatcher
	{
		public var stage:Stage;
		
		private var _context3D:Context3D;
		private var _shaderProgram:Program3D;
		private var _indexBuffer:IndexBuffer3D;
		private var _buffer:VertexBuffer3D;
		private var _viewMatrix:Matrix3D;
		
		public static var instance:MoleHillServer;
		
		public function MoleHillServer(stage:Stage)
		{
			this.stage = stage;
			MoleHillServer.instance = this;
		}
		
		public function startServer():void{
			var stage3D:Stage3D = stage.stage3Ds[0];
			stage3D.addEventListener(Event.CONTEXT3D_CREATE, creatMolehill);
			stage3D.requestContext3D(Context3DRenderMode.AUTO);
		}
		private function creatMolehill(e:Event):void 
		{
			var stage3D:Stage3D = e.target as Stage3D;
			
			_context3D = stage3D.context3D;
			if (_context3D == null)
			{
				trace("oh no, context is null!");
				return;
			}
			
			trace(_context3D.driverInfo);
			try
			{
				_context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 2, false);		
			}
			catch (e:Error)
			{
				trace(e);
			}
			
			_context3D.enableErrorChecking = true;
			var vertexShader:Array =
				[
					"dp4 op.x, va0, vc0", //4x4 matrix transform from 0 to output clipspace
					"dp4 op.y, va0, vc1",
					"dp4 op.z, va0, vc2",
					"dp4 op.w, va0, vc3",
					"mov v0, va1.xyzw"    //copy texcoord from 1 to fragment program
				];
			var vertexAssembler:AGALMiniAssembler = new AGALMiniAssembler();
			vertexAssembler.assemble(flash.display3D.Context3DProgramType.VERTEX, vertexShader.join("\n"));
			
			var fragmentShader:Array =
				[
					"mov ft0, v0			\n" ,
					"tex ft1, ft0, fs1 <2d>	\n" ,	// sample texture 0
					"mov oc, ft1\n"
				];
			var fragmentAssembler:AGALMiniAssembler = new AGALMiniAssembler();
			fragmentAssembler.assemble(flash.display3D.Context3DProgramType.FRAGMENT, fragmentShader.join("\n"));
			
			_shaderProgram = _context3D.createProgram();
			_shaderProgram.upload(vertexAssembler.agalcode, fragmentAssembler.agalcode);
			
			_indexBuffer = _context3D.createIndexBuffer(6);
			_indexBuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 0, 2, 3 ]), 0, 6);
			
			_buffer     = _context3D.createVertexBuffer(4, 4);
			_buffer.uploadFromVector(Vector.<Number>
				([
					-1.0, 1.0, 0.0, 1.0,
					-1.0,-1.0, 0.0, 0.0,
					1.0,-1.0, 1.0, 0.0,
					1.0, 1.0, 1.0, 1.0
				]), 0, 4);
			//_renderList = new Vector.<SpriteMoleHill>;
			_context3D.setVertexBufferAt(0, _buffer, 0, Context3DVertexBufferFormat.FLOAT_2); //xy
			_context3D.setVertexBufferAt(1, _buffer, 2, Context3DVertexBufferFormat.FLOAT_2); //uv
			
			_context3D.setBlendFactors(Context3DBlendFactor.ONE, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA);
			
			_context3D.setProgram(_shaderProgram);
			
			initMatrix();
			
			/*_mapContainer = new MapContainer(_context3D,stage,this);
			_mapContainer.viewMatrix = _viewMatrix;
			_mapContainer.indexBuffer = this._indexBuffer;*/
			
			TexturePool.instance = new TexturePool(_context3D);
			
			this.dispatchEvent(new Event(Event.COMPLETE))
		}
		
		public function initMatrix():void{
			_viewMatrix = new Matrix3D();
			_viewMatrix.appendTranslation(-stage.stageWidth/2, -stage.stageHeight/2, 0);
			_viewMatrix.appendScale(1, -1, 1);
			_viewMatrix.append(new Matrix3D(Vector.<Number>
				([
					2/stage.stageWidth, 0  ,       0,        0,
					0  , 2/stage.stageHeight,       0,        0,
					0  , 0  , 1/100, 0,
					0  , 0  ,       0,        1
				])));
		}

		public function get context3D():Context3D
		{
			return _context3D;
		}

		public function get viewMatrix():Matrix3D
		{
			return _viewMatrix;
		}

		public function get indexBuffer():IndexBuffer3D
		{
			return _indexBuffer;
		}
		
		public function getSpriteBigMolehill():SpriteBIGMoleHill{
			var sprite:SpriteBIGMoleHill = new SpriteBIGMoleHill(this._context3D);
			sprite.viewMatrix = this._viewMatrix;
			sprite.indexBuffer = this._indexBuffer;
			return sprite;
		}
		

		
	}
}